#include "n32g45x.h"
#include "bsp_task.h"
#include "bsp_systick.h"
#include "Drv_led.h"
#include "bsp_key.h"

extern uint8_t key1_pressflag;
extern uint8_t key2_pressflag;
extern uint8_t key3_pressflag;

static uint32_t flow_millis = 500;
static bool flow_dir = false;

static void user_task_flag_change(uint8_t *key_pressflag, void (*action)(void)) {
	if (!(*key_pressflag)) return;
	*key_pressflag = false;
	action();
}

static void toggle_flow_dir(void) {
	flow_dir = !flow_dir;
}

static void increase_flow_millis(void) {
	flow_millis += 100;
}

static void decrease_flow_millis(void) {
	flow_millis -= (flow_millis == 100) ? 0 : 100;
}

static void flow(void) {
	static uint32_t loc_millis;
	if(SYSTICK_GetTime_Ms() - loc_millis < flow_millis) return;
	loc_millis = SYSTICK_GetTime_Ms();

	static uint8_t loc_led = 0;
	loc_led = flow_dir ? loc_led + 1 : loc_led - 1;

	uint32_t target = loc_led % 3;
	switch(target){
		case 0:
			Drv_LED_ON(LED_1);
			Drv_LED_OFF(LED_2);
			Drv_LED_OFF(LED_3);
			break;
		case 1:
			Drv_LED_OFF(LED_1);
			Drv_LED_ON(LED_2);
			Drv_LED_OFF(LED_3);
			break;
		case 2:
			Drv_LED_OFF(LED_1);
			Drv_LED_OFF(LED_2);
			Drv_LED_ON(LED_3);
			break;
		default:
			break;
	}
}

static void Loop_1000Hz(void) 
{
	//////////////////////////////////////////////////////////////////////
	user_task_flag_change(&key1_pressflag, toggle_flow_dir);
	user_task_flag_change(&key2_pressflag, increase_flow_millis);
	user_task_flag_change(&key3_pressflag, decrease_flow_millis);
	flow();
	//////////////////////////////////////////////////////////////////////
}

static void Loop_500Hz(void) 
{
	//////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////
}

static void Loop_200Hz(void) 
{
	//////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////
}

static void Loop_100Hz(void) 
{
	//////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////
}

static void Loop_50Hz(void) 
{
	//////////////////////////////////////////////////////////////////////
	
	
	//////////////////////////////////////////////////////////////////////
}

static void Loop_20Hz(void) 
{
	//////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////
}

static void Loop_2Hz(void) 
{
	//////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////
}

static sched_task_t sched_tasks[] =
	{
		{Loop_1000Hz, 1000, 0, 0},
		{Loop_500Hz, 500, 0, 0},
		{Loop_200Hz, 200, 0, 0},
		{Loop_100Hz, 100, 0, 0},
		{Loop_50Hz, 50, 0, 0},
		{Loop_20Hz, 20, 0, 0},
		{Loop_2Hz, 2, 0, 0},
};

#define TASK_NUM (sizeof(sched_tasks) / sizeof(sched_task_t))

void Scheduler_Setup(void)
{
	uint8_t index = 0;
	
	for (index = 0; index < TASK_NUM; index++)
	{
		
		sched_tasks[index].interval_ticks = TICK_PER_SECOND / sched_tasks[index].rate_hz;
		
		if (sched_tasks[index].interval_ticks < 1)
		{
			sched_tasks[index].interval_ticks = 1;
		}
	}
}

void Scheduler_Run(void)
{
	uint8_t index = 0;

	for (index = 0; index < TASK_NUM; index++)
	{
		uint32_t tnow = SYSTICK_GetTime_Ms();
		
		if (tnow - sched_tasks[index].last_run >= sched_tasks[index].interval_ticks)
		{

			sched_tasks[index].last_run = tnow;

			sched_tasks[index].task_func();
		}
	}
}